package com.prb.factory;

import com.prb.annotation.Transactional;
import com.prb.utils.TransactionManager;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class TransactionalProxyFactory {

    /**
     * jdk 代理
     * @param object
     * @return
     */
    public static Object getJdkProxy(Object object){

        return Proxy.newProxyInstance(TransactionalProxyFactory.class.getClassLoader(), object.getClass().getInterfaces(), (proxy, method, args) -> {

            Object result;

            Class<?> clazz = object.getClass();
            Transactional clazzAnnotation = clazz.getAnnotation(Transactional.class);

            Method method1 = clazz.getMethod(method.getName(), method.getParameterTypes());

            Transactional method1Annotation = method1.getAnnotation(Transactional.class);

            if(clazzAnnotation == null && method1Annotation == null){
                return method.invoke(object , args);
            }else{
                try{
                    TransactionManager.beginTx();
                    result = method.invoke(object, args);
                    TransactionManager.commit();
                }catch (Exception e){
                    TransactionManager.rollback();
                    throw e;
                }
            }
            return result;
        });
    }

    /**
     * cglib 代理
     * @param object
     * @return
     */
    public static Object getCglibProxy(Object object){

        return Enhancer.create(object.getClass(), (MethodInterceptor) (o, method, objects, methodProxy) -> {

            Class<?> clazz = object.getClass();
            Transactional clazzAnnotation = clazz.getAnnotation(Transactional.class);

            Method method1 = clazz.getMethod(method.getName(), method.getParameterTypes());

            Transactional method1Annotation = method1.getAnnotation(Transactional.class);

            Object result;
            if(clazzAnnotation == null && method1Annotation == null){
                return method.invoke(object , objects);
            }else{
                try{
                    TransactionManager.beginTx();
                    result = method.invoke(object, objects);
                    System.out.println("test");
                    TransactionManager.commit();
                }catch (Exception e){
                    TransactionManager.rollback();
                    throw e;
                }
            }
            return result;
        });
    }


}
